<!DOCTYPE html>

<head>
    <title>Computergrafik Projekt WebGL, A.Kuhn M.Ruffer</title>
    
    <script type="text/javascript" src="glMatrix-0.9.5.min.js"></script>    
    
    <script id="shader-fs" type="x-shader/x-fragment">
      precision mediump float;
    
      void main(void) {
        gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
      }
    </script>
    
    <script id="shader-vs" type="x-shader/x-vertex">
      attribute vec3 aVertexPosition;
    
      uniform mat4 uMVMatrix;
      uniform mat4 uPMatrix;
    
      void main(void) {
        gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
      }
    </script>
    
    <script type="text/javascript">
        var gl;
        var canvas;
        
        var triangleVertexPositionBuffer;
        var squareVertexPositionBuffer;
        
        var pMatrix = mat4.create();
        var mvMatrix = mat4.create();
        
        var shaderProgram;
        
        function setMatrixUniforms() {
            gl.uniformMatrix4fv(shaderProgram.pMatrixUniform, false, pMatrix);
            gl.uniformMatrix4fv(shaderProgram.mvMatrixUniform, false, mvMatrix);
        }
    
        
        
        function initGL(canvas){
            try {
                gl = canvas.getContext("experimental-webgl");
                gl.viewportWidth = canvas.width;
                gl.viewportHeight = canvas.height;                
            }
            catch(e){
                window.alert("Fehler: " + e.message);
            }
            
            if(!gl) window.alert("WebGL konnte nicht initialisiert werden.");
        }
        
        function initShaders(){
            var fragmentShader = getShader(gl, "shader-fs");
            var vertexShader = getShader(gl, "shader-vs");
        
            shaderProgram = gl.createProgram();
            gl.attachShader(shaderProgram, vertexShader);
            gl.attachShader(shaderProgram, fragmentShader);
            gl.linkProgram(shaderProgram);
        
            if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
              window.alert("Could not initialise shaders");
            }
        
            gl.useProgram(shaderProgram);;
            
            shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
            gl.enableVertexAttribArray(shaderProgram. vertexPositionAttribute);
            
            shaderProgram.pMatrixUniform = gl.getUniformLocation(shaderProgram, "uPMatrix");
            shaderProgram.pMatrixUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix");
        }
        
        function getShader(gl, id) {
            var shaderScript = document.getElementById(id);
            if (!shaderScript) {
                return null;
            }
        
            var str = "";
            var k = shaderScript.firstChild;
            while (k) {
                if (k.nodeType == 3){
                    str += k.textContent;
                }
                k = k.nextSibling;
            }
        
            var shader;
            if (shaderScript.type == "x-shader/x-fragment") {
                shader = gl.createShader(gl.FRAGMENT_SHADER);
            } else if (shaderScript.type == "x-shader/x-vertex") {
                shader = gl.createShader(gl.VERTEX_SHADER);
            } else {
                return null;
            }
        
            gl.shaderSource(shader, str);
            gl.compileShader(shader);
        
            if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
                window.alert(gl.getShaderInfoLog(shader));
                return null;
            }
        
            return shader;
        }
        
        function initBuffers(){
            triangleVertexPositionBuffer = gl.createBuffer();
            squareVertexPositionBuffer = gl.createBuffer();
            
            /* ***** DREIECK ****** */
            /* Buffer binden. dies ist der aktuelle buffer. es wird immer auf dem aktuellen buffer gerechnet. */
            gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexPositionBuffer);
            var vertices = [
                0.0,    1.0,    0.0,
                -1.0,   -1.0,   0.0,
                1.0,    -1.0,   0.0
            ];
            /* vertexe in den aktuellen buffer schiebene */
            gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
            
            /* zusätzliche eigenschaften festlegen */
            triangleVertexPositionBuffer.itemSize = 3;
            triangleVertexPositionBuffer.numItems = 3;
            
            /* ***** QUADRAT ***** */
            gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexPositionBuffer);
            vertices = [
                0.0,    0.0,    0.0,
                1.0,    0.0,    0.0,
                0.0,    1.0,    0.0,
                1.0,    1.0,    0.0
            ];
            gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
            squareVertexPositionBuffer.itemSize = 3;
            squareVertexPositionBuffer.numItems = 4;
        }
        
        function drawScene(){
            gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
            gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
            
            /*
                perspektive festlegen:
                    45° blickwinkel
                    seitenverhältnis des canvas
                    nur elemente, die weiter weg sind als 0.1 einheiten
                    nur elemente, die näher sind als 100 einheiten
                    
            */
            mat4.perspective(45, gl.viewportWidth / gl.viewportHeight, 0.1, 100.0, pMatrix);
            
            mat4.identity(mvMatrix);
            
            /* ***** Dreieck ***** */
            mat4.translate(mvMatrix, [-1.5, 0.0, -7.0]);
            gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexPositionBuffer);
            gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, triangleVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
            setMatrixUniforms();
            gl.drawArrays(gl.TRIANGLES, 0, triangleVertexPositionBuffer.numItems);
            
            /* ***** Quadrat ***** */
            mat4.translate(mvMatrix, [4.5, 0.0, 0.0]);
            gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexPositionBuffer);
            gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, squareVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
            setMatrixUniforms();
            gl.drawArrays(gl.TRIANGLE_STRIP, 0, squareVertexPositionBuffer.numItems);            
        }
        
        /**
         * Initialisiere WebGL
         */                 
        function initWebGL(){
            canvas = document.getElementById("webgl_canvas");
            initGL(canvas);
            initShaders();
            initBuffers();
            
            gl.clearColor(0.0, 0.0, 0.0, 1.0);
            gl.enable(gl.DEPTH_TEST);
            
            drawScene();
        }
    </script>
</head>

<body onload="initWebGL();">

    <canvas id="webgl_canvas" style="border: 1px solid black;" width="500" height="500">
    </canvas>
    
    <br />
    <br />
    <p>Computergrafik Projekt WebGL, A.Kuhn M.Ruffer</p>
 
</body>